EC2 Image Builder を使用して 作成した AMI で 起動時に一度だけプログラムを実行するにはどうしたらいいですか?
困っていた内容
AMI起動時に一度だけプログラムを実行させたい場合は
/var/lib/cloud/scripts/per-once/
配下にスクリプトを作成しておくことで可能でしたが、EC2 Image Builder を使用して AMI を作成した時は、Security best practicesのスクリプトが強制的に実施され、/var/lib/cloud/
配下が削除されてしまいます。
他にも削除されてしまうファイルがありますので詳しくはドキュメントをご参照ください。
Security best practices for EC2 Image Builder
The following script is run as a mandatory step when Linux images are customized with EC2 Image Builder.
どうすればいいの?
/var/lib/cloud/
配下が削除されてしまいますので、削除されない場所にスクリプトを置いて、cloud-initの代わりに独自にユニットファイルを作成して、サービスを登録したAMIを作成します。
やってみる
今回は、一度だけ実行したいので、cloud-initのときと同じように、lock fileの有無で実行するかしないかを判断します。
例) cloud.initの場合は、以下ファイルの有無で判断しています。 /var/lib/cloud/sem/config_scripts_per_once.once
スクリプトを作成する
一度だけ実行したいスクリプト
/home/ec2-user/per-once.txt
にper once!
と書き込むスクリプトを作成しました。
- /root/per-once/scripts/per_once.sh
$ sudo vi /root/per-once/scripts/per_once.sh
#!/bin/bash FILE="/root/per-once/scripts/per_once.lock" # ロックファイルがあったら終了 if [ -e $FILE ]; then echo "exist lock file" exit fi # 実行 cat <<EOF >> /home/ec2-user/per-once.txt per once ! EOF # 実行したらlockファイルを作成する touch /root/per-once/scripts/per_once.lock
$ sudo chmod +x /root/per-once/scripts/per_once.sh
ユニットファイルを作成する
$ sudo vi /etc/systemd/system/test.service
[Unit] Description=per once script After=cloud-init.target [Service] Restart=no Type=simple RemainAfterExit=yes ExecStart=/root/per-once/scripts/per_once.sh [Install] WantedBy=cloud-init.target
自動起動の設定
$ sudo systemctl enable test Created symlink from /etc/sys:q! ::temd/system/cloud-init.target.wants/test.service to /etc/systemd/system/test.service.
$ sudo systemctl is-enabled test enabled
上記、設定をAMIにしておきます。
参考までに、ansible playbook で作成した時は以下のようになります。
playbook.yml
- hosts: 127.0.0.1 become: yes roles: - setup
├── playbook.yml └── roles ├── setup │ ├── files │ │ ├── per_once.sh │ │ └── test.service │ └── tasks │ └── main.yml
roles/setup/tasks/main.yml
--- - name: mkdir scripts file: path: /root/per-once/scripts state: directory recurse: yes - name: Copy /root/scripts/per_once.sh copy: src: files/per_once.sh dest: /root/per-once/scripts/per_once.sh mode: a+x - name: Copy /etc/systemd/system/test.service copy: src: files/test.service dest: /etc/systemd/system/test.service mode: 0644 - name: Enable test service systemd: name: test enabled: yes
Ansible playbookを実行する方法は以下エントリーを見てください。
EC2 Image Builder で Rolesディレクトリを使用してる Ansible Playbook を実行するにはどうしたらいいですか?
確認
AMIから初回起動、ロックファイルが作成され、2回目以降は書き込まれないことを確認します。
$ cat /home/ec2-user/per-once.txt per once !
# ll /root/per-once/scripts/ total 4 -rw-r--r-- 1 root root 0 Oct 26 22:29 per_once.lock -rwx--x--x 1 root root 320 Oct 26 22:16 per_once.sh
おまけ
一度だけ実行なので、lockファイルの作成じゃなく、サービスの無効化や削除する方法
/etc/systemd/system/test.service
のExecStart
で以下のように対応します。
- 無効化する
ExecStart=/bin/bash -c "/root/per-once/scripts/per_once.sh && /usr/bin/systemctl disable test"
- 削除する
ExecStart=/bin/bash -c "/root/per-once/scripts/per_once.sh && /usr/bin/systemctl disable test && rm -rf /etc/systemd/system/test.service /root/per-once"